/*
 * ============================================================================
 *
 *       Filename:  QQWryCompress.h
 *
 *    Description:  Declaration of class compressing ip record
 *
 *         Author:  liangqing
 *
 * ============================================================================
 */
#ifndef IPRECORDCOMPRESS_H
#define IPRECORDCOMPRESS_H

#include "IPRecordReader.h"
#include <fstream>
#include <string>

//#define USE_HASH_MAP

#ifdef USE_SET
#include <set>
#else
#include <vector>
#include <algorithm>
#endif /* USE_SET */

#ifdef USE_HASH_MAP
#ifdef __GNUC__ 
#include <ext/hash_map>
namespace __gnu_cxx
{
        template<> struct hash< std::string >
        {
                size_t operator()( const std::string& x ) const
                {
                        return hash< const char* >()( x.c_str() );
                }
        };
}
#else
#include <hash_map>
#endif /* __GNUC__ */
#else
#include <map>
#endif /* USE_HASH_MAP */

class QQWryCompress {
  public:
    QQWryCompress(const char *filename);
    
    ~QQWryCompress(){ _qqwry.close(); if(_buf) delete []_buf;}
    //~QQWryCompress(){ fclose(_qqwry); }
   
    bool put(IPRecord *record);

    bool finish();
    
    inline int total(){ return _count; }

    inline int file_size(){ return _file_size; }

  protected:
#ifdef USE_HASH_MAP
#ifdef __GNUC__
    typedef __gnu_cxx::hash_map<std::string, int> StrMap;
#else
    typedef stdext::hash_map<std::string, int> StrMap;
#endif /* __GNUC__ */
#else
    typedef std::map<std::string, int> StrMap;
#endif /* USE_HASH_MAP */
    
    struct StrResource {
        int offset;
        StrMap sections;
    };

#ifdef USE_HASH_MAP
#ifdef __GNUC__
    typedef __gnu_cxx::hash_map<std::string, StrResource> ResourceMap;
#else
    typedef stdext::hash_map<std::string, StrResource> ResourceMap;
#endif /* __GNUC__ */
#else
    typedef std::map<std::string, StrResource> ResourceMap;
#endif /* USE_HASH_MAP */
    
#ifdef USE_SET
    typedef std::set<Index> IndexContainer;
#else
    typedef std::vector<Index> IndexContainer;
#endif /* USE_SET */

    inline int _write(const char *buf, int size);

    inline void _put(const char c);
    
    inline void _seek(int pos);
    
    inline bool _push_index(Index &index);
    
    inline int _output_offset(int integer, char *offset, int size=3);

    std::ofstream _qqwry;
    //FILE *_qqwry;
    ResourceMap _strings;
    IndexContainer _indexes;

    int _count;
    int _file_size;
    char *_buf;
    std::streambuf *_sbuf;
};

#endif   /* #ifndef IPRECORDCOMPRESS_H */
